package com.distribution.system.service.impl;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.IdcardUtil;
import cn.hutool.core.util.PhoneUtil;
import cn.hutool.core.util.ReUtil;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.distribution.common.core.domain.entity.SysUser;
import com.distribution.common.core.redis.RedisCache;
import com.distribution.common.exception.ServiceException;
import com.distribution.common.utils.DictUtils;
import com.distribution.common.utils.StringUtils;
import com.distribution.system.domain.bo.*;
import com.distribution.system.domain.converter.ProductFlowInfoConverter;
import com.distribution.system.domain.converter.UnOrderOperationServiceConverter;
import com.distribution.system.domain.dto.ChoosePhoneDTO;
import com.distribution.system.domain.dto.OrderSearchDTO;
import com.distribution.system.domain.dto.SendCodeDTO;
import com.distribution.system.domain.dto.PlaceOrderDTO;
import com.distribution.system.domain.entity.*;
import com.distribution.system.domain.req.ReqResult;
import com.distribution.system.enums.OrderStatusEnum;
import com.distribution.system.manager.attributioncode.AttributionCodeMateManager;
import com.distribution.system.manager.channel.Channel;
import com.distribution.system.manager.channel.ChannelManager;
import com.distribution.system.manager.zoningcode.ZoningCodeMateManager;
import com.distribution.system.mapper.SysUserMapper;
import com.distribution.system.service.*;
import com.distribution.system.utils.EncryptionUtil;
import com.distribution.system.utils.IdCardNumberMethod;
import com.distribution.system.utils.zop.ZopUtil;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * @author destinyhlp
 * @date 2023/6/2 04:32
 */

@Slf4j
@Service
public class PlaceOrderOperationServiceImpl implements PlaceOrderOperationService {
    private static final Logger productFlowLog = LoggerFactory.getLogger("productFlowLog");
    private static final Logger placeOrderLog = LoggerFactory.getLogger("placeOrderLog");
    private static final Logger choosePhoneLog = LoggerFactory.getLogger("choosePhoneLog");
    private static final Logger smsCodeLog = LoggerFactory.getLogger("smsCodeLog");

    private static final int SUCCESS_CODE = 200;

    @Resource
    ZoningCodeMateManager zoningCodeMateManager;
    @Resource
    AttributionCodeMateManager attributionCodeMateManager;
    @Resource
    ChannelManager channelManager;
    @Resource
    UnOrderOperationServiceConverter unOrderOperationServiceConverter;
    @Resource
    CmccDaAccountDetailService cmccDaAccountDetailService;
    @Resource
    ISysUserService iSysUserService;
    @Resource
    SysUserMapper sysUserMapper;
    @Resource
    CmccDaProductService cmccDaProductService;
    @Resource
    CmccDaOrderService cmccDaOrderService;
    @Resource
    AddressSystemService addressSystemService;
    @Resource
    AddressChannelService addressChannelService;
    @Resource
    CmccDaProxyProductManageService cmccDaProxyProductManageService;
    @Resource
    CmccDaAreaFlowService cmccDaAreaFlowService;
    @Resource
    CmccDaDistanceFlowService cmccDaDistanceFlowService;
    @Resource
    CmccDaChildCardService cmccDaChildCardService;
    @Resource
    CmccDaOperatorFlowService cmccDaOperatorFlowService;
    @Resource
    RedisCache redisCache;
    @Resource
    ProductFlowInfoConverter productFlowInfoConverter;

    /**
     * @param sendCodeDTO 验证码信息
     * @Author: GodLu
     * @Date: 2024/5/24 16:49
     * @Description: 发送验证码
     * @return: JSONObject
     */
    @Override
    public ReqResult sendVerificationCode(SendCodeDTO sendCodeDTO) {
        smsCodeLog.info("发送验证码信息：" + sendCodeDTO);
        log.info("发送验证码信息：" + sendCodeDTO);
        CmccDaProduct beforeFlowProduct = cmccDaProductService.getOne(new LambdaQueryWrapper<CmccDaProduct>()
                .eq(CmccDaProduct::getProductCode, sendCodeDTO.getProductCode()),false);
        if (beforeFlowProduct == null) return ReqResult.error("当前产品不存在或已下架");
        // 参数校验
        if (!PhoneUtil.isPhone(sendCodeDTO.getCustomerPhone())) {
            return ReqResult.error("联系电话格式不正确");
        }
        if (beforeFlowProduct.getProductTypeId() != 6) {// 非流量包类型需要校验其他
            /*if (!Validator.isChinese(sendCodeDTO.getCertName())
                    || sendCodeDTO.getCertName().length() < 2 || sendCodeDTO.getCertName().length() > 6) {
                return ReqResult.error("姓名格式不正确");
            }*/
            if (!IdcardUtil.isValidCard(sendCodeDTO.getCertNum())) {
                return ReqResult.error("身份证号格式不正确");
            }
            if (StringUtils.isBlank(sendCodeDTO.getAddressProvinceCode()) || StringUtils.isBlank(sendCodeDTO.getAddressCityCode())
                    || StringUtils.isBlank(sendCodeDTO.getAddressAreaCode())) {
                return ReqResult.error("收货地址省市区编码不能为空");
            }
            // 如果不是宽带则验证归属地
            if (!"1".equals(beforeFlowProduct.getBroadbandFlag())){
                if (StringUtils.isBlank(sendCodeDTO.getAttributionProvinceCode()) || StringUtils.isBlank(sendCodeDTO.getAttributionCityCode())) {
                    return ReqResult.error("归属地省市编码不能为空");
                }
            }
        }
        // 分流
        ProductFlowInfo productFlowInfo = productFlowInfoConverter.sendCodeDtoToProductFlowInfo(sendCodeDTO);
        CmccDaProduct afterFlowProduct = getAfterFlowProduct(beforeFlowProduct, productFlowInfo);
        if (afterFlowProduct != null){
            return doSendSmsCode(sendCodeDTO,afterFlowProduct);
        }
        return doSendSmsCode(sendCodeDTO, beforeFlowProduct);
    }
    private ReqResult doSendSmsCode(SendCodeDTO sendCodeDTO, CmccDaProduct unOrderProduct){
        Channel defaultChannel = channelManager.getDefaultChannel(Integer.valueOf(unOrderProduct.getBindChannelInfoId()));
        return defaultChannel.sendSmsCode(unOrderProduct,sendCodeDTO);
    }

    @Override
    public ReqResult choosePhone(ChoosePhoneDTO choosePhoneDTO) {
        choosePhoneLog.info("选号信息：" + choosePhoneDTO);
        log.info("选号信息：" + choosePhoneDTO);
        // 根据产品ID获取卡信息
        CmccDaProduct beforeFlowProduct = cmccDaProductService.getOne(new LambdaQueryWrapper<CmccDaProduct>()
                .eq(CmccDaProduct::getProductCode, choosePhoneDTO.getProductCode()), false);
        // 分流
        ProductFlowInfo productFlowInfo = productFlowInfoConverter.choosePhoneDtoToProductFlowInfo(choosePhoneDTO);
        CmccDaProduct afterFlowProduct = getAfterFlowProduct(beforeFlowProduct, productFlowInfo);
        if (afterFlowProduct != null){
            // 如果分流了就redis缓存
            redisCache.setCacheObject(choosePhoneDTO.getCertName() + choosePhoneDTO.getCertNum() + beforeFlowProduct.getProductCode(),
                    afterFlowProduct.getProductCode(),1, TimeUnit.HOURS);
            return doChoosePhone(choosePhoneDTO,afterFlowProduct);
        }
        // 未分流则删除redis缓存
        redisCache.deleteObject(choosePhoneDTO.getCertName() + choosePhoneDTO.getCertNum() + beforeFlowProduct.getProductCode());
        return doChoosePhone(choosePhoneDTO,beforeFlowProduct);
    }
    private ReqResult doChoosePhone(ChoosePhoneDTO choosePhoneDTO, CmccDaProduct placeOrderProduct){
        // 下单卡信息不能为空
        if (placeOrderProduct == null) return ReqResult.error("商品编码错误");
        ReqResult areaReqResult = cmccDaProductService.checkBanArea(choosePhoneDTO.getAddressProvinceCode(), placeOrderProduct);
        if (areaReqResult.getCode() != 200) return areaReqResult;
        // 聚合卡选号
        if ("1".equals(placeOrderProduct.getMergeProductFlag())){
            //查询归属地省份与用户下单地区省份相同分卡
            List<CmccDaChildCard> provinceChildCardList = cmccDaChildCardService.list(new LambdaQueryWrapper<CmccDaChildCard>()
                    .eq(CmccDaChildCard::getRegularProvinceCode, choosePhoneDTO.getAttributeProvinceCode())
                    .eq(CmccDaChildCard::getParentCode,placeOrderProduct.getProductCode()));
            //没有与用户下单省份相同归属地的分卡则选号失败
            if (provinceChildCardList == null || provinceChildCardList.isEmpty()) {
                return ReqResult.error(choosePhoneDTO.getAddressProvince() + "地区无法下单");
            }
            //查询归属地城市与用户下单城市相同的分卡
            for (CmccDaChildCard cityChildCard : provinceChildCardList) {
                //有则使用省市都一致的分卡选号
                if (choosePhoneDTO.getAttributeCityCode().equals(cityChildCard.getRegularCityCode())){
                    placeOrderProduct.setProductParam(cityChildCard.getProductParam());
                    return doChoosePhone(choosePhoneDTO,placeOrderProduct);
                }
            }
            //没有则使用省名称一致的分卡选号
            CmccDaChildCard provinceChildCard = provinceChildCardList.get(0);
            placeOrderProduct.setProductParam(provinceChildCard.getProductParam());
        }
        //向三方发送请求
        Channel defaultChannel = channelManager.getDefaultChannel(Integer.valueOf(placeOrderProduct.getBindChannelInfoId()));
        ReqResult reqResult = defaultChannel.choosePhone(choosePhoneDTO,placeOrderProduct,addressChannelService);
        if (reqResult.getCode() == 200) {
            ChoosePhoneResultBO choosePhoneResultBO = (ChoosePhoneResultBO) reqResult.getData();
            List<String> numArray = choosePhoneResultBO.getNumArray();
            //这里返回号码列表有的包含空格，手动去除
            numArray.replaceAll(s -> s.trim().replaceAll("\\s+", ""));
            if (numArray.isEmpty()) {
                return ReqResult.error("请求号码成功，当前地区没有可选号码");
            }else {
                return ReqResult.success(choosePhoneResultBO);
            }
        } else {
            //throw new ServiceException(reqResult.get("msg").toString());
            return ReqResult.error(reqResult.getMsg());
        }
    }

    @Override
    public ReqResult placeOrder(PlaceOrderDTO placeOrderDto) {
        log.info("下单信息：" + placeOrderDto);
        placeOrderLog.info("下单信息：" + placeOrderDto);
        // 解码userId
        String userId = EncryptionUtil.decodeBase64(placeOrderDto.getUserId());
        // 获取商品编码
        String productCode = placeOrderDto.getProductCode();
        // 解码userId，获取用户信息
        placeOrderDto.setUserId(userId);
        SysUser sysUser = iSysUserService.selectUserById(Long.parseLong(placeOrderDto.getUserId()));
        // 根据产品ID获取卡信息
        CmccDaProduct beforeFlowProduct = cmccDaProductService.getOne(new LambdaQueryWrapper<CmccDaProduct>()
                .eq(CmccDaProduct::getProductCode, productCode), false);
        // 如果当前卡需要选号则在redis中取出选号阶段已经分流的卡信息直接下单，否则需要判断分流
        if ("1".equals(beforeFlowProduct.getSelectNumberFlag())){
            String afterFlowProductCode = redisCache.getCacheObject(placeOrderDto.getCustomerName() + placeOrderDto.getCustomerCertNo()
                    + beforeFlowProduct.getProductCode());
            if (afterFlowProductCode != null){
                CmccDaProduct afterFlowCard = cmccDaProductService.getOne(new LambdaQueryWrapper<CmccDaProduct>()
                        .eq(CmccDaProduct::getProductCode, afterFlowProductCode), false);
                if (afterFlowCard != null) {
                    flowDistribute(placeOrderDto, afterFlowCard);
                    return doPlaceOrder(sysUser, placeOrderDto, afterFlowCard, beforeFlowProduct);
                }
                return ReqResult.error("下单失败，请重新选号");
            }
        }
        // 分流
        ProductFlowInfo productFlowInfo = productFlowInfoConverter.placeOrderDtoToProductFlowInfo(placeOrderDto);
        CmccDaProduct afterFlowProduct = getAfterFlowProduct(beforeFlowProduct, productFlowInfo);
        if (afterFlowProduct != null){
            flowDistribute(placeOrderDto, afterFlowProduct);
            return doPlaceOrder(sysUser, placeOrderDto, afterFlowProduct, beforeFlowProduct);
        }
        //下单
        return doPlaceOrder(sysUser, placeOrderDto, beforeFlowProduct,null);
    }

    private ReqResult checkPlaceOrderParam(PlaceOrderDTO placeOrderDto, CmccDaProduct product){
        if (product == null){
            return ReqResult.error("当前产品不存在或已下架");
        }
        // 参数校验
        if (!PhoneUtil.isPhone(placeOrderDto.getCustomerPhone())) {
            return ReqResult.error("联系电话格式不正确");
        }
        if (product.getProductTypeId() != 6) {// 非流量包类型需要校验其他
            /*if (!Validator.isChinese(placeOrderDto.getCustomerName())
                    || placeOrderDto.getCustomerName().length() < 2 || placeOrderDto.getCustomerName().length() > 6) {
                return ReqResult.error("姓名格式不正确");
            }*/
            if (!IdcardUtil.isValidCard(placeOrderDto.getCustomerCertNo())) {
                return ReqResult.error("身份证号格式不正确");
            }
            if (StringUtils.isBlank(placeOrderDto.getAddressProvinceCode()) || StringUtils.isBlank(placeOrderDto.getAddressCityCode())
                    || StringUtils.isBlank(placeOrderDto.getAddressDistrictCode())) {
                return ReqResult.error("收货地址省市区编码不能为空");
            }
            if (StringUtils.isBlank(placeOrderDto.getAddressStreet())) {
                return ReqResult.error("详细地址不能为空");
            }
            if (ReUtil.isMatch("^(\\\\+86)?1[3-9]\\\\d{9}$", placeOrderDto.getAddressStreet())) {
                return ReqResult.error("详细地址中不能包含手机号");
            }
            if (StringUtils.isBlank(placeOrderDto.getAttributeProvinceCode()) || StringUtils.isBlank(placeOrderDto.getAttributeCityCode())) {
                return ReqResult.error("归属地省市编码不能为空");
            }
            if ("1".equals(product.getCodeFlag()) && StringUtils.isBlank(placeOrderDto.getCode())) {
                return ReqResult.error("验证码不能为空");
            }
            if ("1".equals(product.getSelectNumberFlag()) && StringUtils.isBlank(placeOrderDto.getChoosePhone())){
                return ReqResult.error("选购号码不能为空");
            }
        }else {// 流量包需要校验订购路径
            if (StringUtils.isBlank(placeOrderDto.getSubscribePath())) {
                return ReqResult.error("订购路径不能为空");
            }
        }
        return ReqResult.success();
    }
    private ReqResult checkPlaceOrderPermission(CmccDaProduct beforeFlowProduct, SysUser sysUser){
        if (sysUser == null) {
            return ReqResult.error("用户不存在或链接失效,请重新复制下单链接!");
        }
        //System.out.println("sysUser = " + sysUser);
        if (sysUser.isAgentOperation() || sysUser.isOperationSupervisor() || sysUser.getRoleId() == 104) {
            return ReqResult.error("内部员工账号禁止下单!");
        }
        CmccDaProxyProductManage cmccDaProxyProductManage = cmccDaProxyProductManageService.getOne(new LambdaQueryWrapper<CmccDaProxyProductManage>()
                .eq(CmccDaProxyProductManage::getUserId,sysUser.getUserId())
                .eq(CmccDaProxyProductManage::getProductCode,beforeFlowProduct.getProductCode()),false);
        if (cmccDaProxyProductManage == null || cmccDaProxyProductManage.getProductState() == 0) {
            return ReqResult.error("抱歉，您暂时未开通此商品!");
        }
        if (cmccDaProxyProductManage.getCommission().compareTo(BigDecimal.ZERO) <= 0) {
            return ReqResult.error("此商品佣金为零，不允许下单!");
        }
        return ReqResult.success();
    }
    private ReqResult checkTodayOrderLimit(CmccDaProduct product, SysUser sysUser){
        // 获取代理当日限单
        int agentTodayOrderLimit = sysUser.getTodayOrderLimit() == null ? 0 : sysUser.getTodayOrderLimit();
        // 获取商品当日限单
        int productTodayOrderLimit = Objects.isNull(product.getProductTodayOrderLimit()) ? 0 : product.getProductTodayOrderLimit();
        // 查商品配置信息
        Long userId = sysUser.getUserId();
        String productCode = product.getProductCode();
        CmccDaProxyProductManage one = cmccDaProxyProductManageService.lambdaQuery()
                .eq(CmccDaProxyProductManage::getUserId, userId)
                .eq(CmccDaProxyProductManage::getProductCode, productCode).one();
        // 获取代理商品当日限单
        if (one == null){
            placeOrderLog.error("代理【{}】商品【{}】配置信息不存在或存在多条记录", userId, productCode);
            return ReqResult.error("商品配置异常，请联系管理员");
        }
        int agentProductTodayOrderLimit = one.getTodayOrderLimit() == null ? 0 : one.getTodayOrderLimit();
        if (agentTodayOrderLimit == 0 && productTodayOrderLimit == 0 && agentProductTodayOrderLimit == 0) return ReqResult.success();
        // 查当前代理今日除失败订单
        LocalDateTime beginTime = DateUtil.beginOfDay(DateUtil.date()).toLocalDateTime();
        LocalDateTime endTime = DateUtil.endOfDay(DateUtil.date()).toLocalDateTime();
        List<CmccDaOrder> agentTodayOrderList = cmccDaOrderService.lambdaQuery()
                .eq(CmccDaOrder::getUserId, userId)
                .ne(CmccDaOrder::getOrderStatus, "0")
                .ge(CmccDaOrder::getCreateTime, beginTime)
                .le(CmccDaOrder::getCreateTime, endTime).list();
        if (agentTodayOrderLimit > 0){
            // 若今日该代理单量 ≥ 代理当日限单，则返回失败信息
            if (agentTodayOrderList.size() >= agentTodayOrderLimit){
                return ReqResult.error("该代理当日订单已达上限");
            }
        }
        // 查当前商品今日除失败订单
        List<CmccDaOrder> productTodayOrderList = cmccDaOrderService.lambdaQuery()
                .eq(CmccDaOrder::getProductCode, productCode)
                .ne(CmccDaOrder::getOrderStatus, "0")
                .ge(CmccDaOrder::getCreateTime, beginTime)
                .le(CmccDaOrder::getCreateTime, endTime).list();
        if (productTodayOrderLimit > 0) {
            // 若今日该商品单量 ≥ 商品当日限单，则返回失败信息
            if (productTodayOrderList.size() >= productTodayOrderLimit) {
                return ReqResult.error("该商品当日订单已达上限");
            }
        }
        // 过滤当前代理该商品今日单量
        List<CmccDaOrder> agentProductTodayOrderList = productTodayOrderList.stream().filter(f -> f.getUserId().equals(userId)).collect(Collectors.toList());
        if (agentProductTodayOrderLimit > 0){
            // 若当前代理该商品今日单量 ≥ 代理当日限单，则返回失败信息
            if (agentProductTodayOrderList.size() >= agentProductTodayOrderLimit){
                return ReqResult.error("该代理当前商品当日订单已达上限");
            }
        }
        // 返回成功信息
        return ReqResult.success();
    }
    private void flowDistribute(PlaceOrderDTO placeOrderDto, CmccDaProduct afterFlowCard) {
        if (afterFlowCard != null) {
            placeOrderDto.setProductCode(afterFlowCard.getProductCode());
            placeOrderDto.setProductParam(afterFlowCard.getProductParam());
        }
    }

    /**
    * @Author: GodLu
    * @Date: 2024/4/2 10:38
    * @Description: 开始下单
    * @param sysUser 下单用户信息
    * @param placeOrderDto 下单信息
    * @param cmccDaProduct 下单卡信息
    * @param beforeFlowProduct 分流前卡信息(为空则没有分流)
    * @return: JSONObject
    */
    public ReqResult doPlaceOrder(SysUser sysUser, PlaceOrderDTO placeOrderDto, CmccDaProduct cmccDaProduct, CmccDaProduct beforeFlowProduct) {
        // 校验参数
        ReqResult paramReqResult = checkPlaceOrderParam(placeOrderDto, cmccDaProduct);
        if (paramReqResult.getCode() != 200) return paramReqResult;
        // 检查下单权限
        ReqResult permissionReqResult = checkPlaceOrderPermission(cmccDaProduct, sysUser);
        if (permissionReqResult.getCode() != 200) return permissionReqResult;
        // 是否为屏蔽地区
        ReqResult areaReqResult = cmccDaProductService.checkBanArea(placeOrderDto.getAddressProvinceCode(), cmccDaProduct);
        if (areaReqResult.getCode() != 200) return areaReqResult;
        // 生成订单
        CmccDaOrder cmccDaOrder = genOrder(sysUser, placeOrderDto, cmccDaProduct);
        // 检查当日限单
        ReqResult OrderLimitReqResult = checkTodayOrderLimit(cmccDaProduct, sysUser);
        if (OrderLimitReqResult.getCode() != 200) return OrderLimitReqResult;
        /*// 限制指定商品每个代理每天最多下10单
        List<String> productCodeList = Arrays.asList("250113001","250113002");
        Long userId = cmccDaOrder.getUserId();
        String productCode = cmccDaOrder.getProductCode();
        if (productCodeList.contains(productCode)){
            int todayPlaceSuccessOrderCount = cmccDaOrderService.getTodayPlaceSuccessOrderCount(userId, productCodeList);
//        System.out.println("todayPlaceSuccessOrderCount = " + todayPlaceSuccessOrderCount);
            if (todayPlaceSuccessOrderCount >= 10){
                log.info("代理【{}】产品【{}】当日下单已达上限", userId, productCode);
                placeOrderLog.info("代理【{}】产品【{}】当日下单已达上限", userId, productCode);
                cmccDaOrder.setOrderStatus(OrderStatusEnum.FAIL.getOrderStatus());
                cmccDaOrder.setOrderStatusDesc(OrderStatusEnum.FAIL.getOrderStatusDesc());
                cmccDaOrder.setFailureReason("当日下单已达上限");
                //保存客户订单信息
                cmccDaOrderService.save(cmccDaOrder);
                return ReqResult.error("当日下单已达上限");
            }
        }*/
        /** ========================================聚合卡下单===================================== */
        //是聚合卡
        if ("1".equals(cmccDaProduct.getMergeProductFlag())){
            // 查询归属地与用户下单地区相同分卡
            List<CmccDaChildCard> cmccDaChildCardList = cmccDaChildCardService.list(new LambdaQueryWrapper<CmccDaChildCard>()
                    .eq(CmccDaChildCard::getRegularProvinceCode, placeOrderDto.getAttributeProvinceCode())
                    .eq(CmccDaChildCard::getParentCode,cmccDaProduct.getProductCode()));
            // 没有与用户下单地区相同归属地的分卡则下单失败
            if (cmccDaChildCardList == null || cmccDaChildCardList.isEmpty()) {
                cmccDaOrder.setFailureReason(placeOrderDto.getAddressProvince() + "地区无法下单");
                cmccDaOrder.setOrderStatus(OrderStatusEnum.FAIL.getOrderStatus());
                cmccDaOrder.setOrderStatusDesc(OrderStatusEnum.FAIL.getOrderStatusDesc());
                //保存客户订单信息
                cmccDaOrderService.save(cmccDaOrder);
                return ReqResult.error(placeOrderDto.getAddressProvince() + "地区无法下单");
            }
            //根据分卡信息设置订单信息
            CmccDaChildCard cmccDaChildCard = cmccDaChildCardList.get(0);
            //查询归属地城市与用户下单城市相同的分卡
            for (CmccDaChildCard childCard : cmccDaChildCardList) {
                //有则使用省市都一致的分卡选号
                if (placeOrderDto.getAttributeCityCode().equals(childCard.getRegularCityCode())){
                    cmccDaChildCard = childCard;
                }
            }
            cmccDaOrder.setProductParam(cmccDaChildCard.getProductParam());
            //设置聚合卡名称为“聚合卡名称【分卡名称】”
            cmccDaOrder.setProductName(cmccDaProduct.getProductName() + "【" + cmccDaChildCard.getProductName() + "】");
            cmccDaOrder.setProductTypeId(cmccDaChildCard.getProductTypeId());
            cmccDaOrder.setBindChannelInfoId(cmccDaChildCard.getBindChannelInfoId());
        }

        /** ==========================================正常下单========================================= */
        //发送请求到第三方接口
        ReqResult channelReqResult = sendPlaceOrderRequestToChannel(cmccDaOrder, cmccDaProduct);
        // 如果分流则下单完成后设置商品编码为分流前的商品编码
        if (beforeFlowProduct != null) {
            cmccDaOrder.setProductCode(beforeFlowProduct.getProductCode());
        }
        if (channelReqResult.getCode() == 200) {
            //将客户订单添加到资金明细
            List<CmccDaAccountDetail> cmccDaAccountDetails = cmccDaAccountDetailService.addAccountDetailByOrder(cmccDaOrder);
            //设置佣金
            if (!cmccDaAccountDetails.isEmpty()) {
                BigDecimal reduce = cmccDaAccountDetails.stream().map(CmccDaAccountDetail::getChangeAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
                log.info("设置订单编号为【{}】的订单佣金为【{}】", cmccDaOrder.getOrderId(), reduce);
                placeOrderLog.info("设置订单编号为【{}】的订单佣金为【{}】", cmccDaOrder.getOrderId(), reduce);
                cmccDaOrder.setCommission(reduce);//佣金
                // 获取商品的基础佣金
                BigDecimal basicCommission = beforeFlowProduct == null ? cmccDaProduct.getBasicsCommission() : beforeFlowProduct.getBasicsCommission();
                BigDecimal subtract = reduce.subtract(basicCommission);
                if (subtract.compareTo(BigDecimal.ZERO) > 0) {
                    BigDecimal points = BigDecimal.valueOf(10.0).subtract(subtract).compareTo(BigDecimal.ZERO) > 0 ?
                            BigDecimal.valueOf(10.0).subtract(subtract).divide(BigDecimal.valueOf(10.0), 1, RoundingMode.HALF_UP) : BigDecimal.ZERO;
                    cmccDaOrder.setPoints(points);
                }else {
                    cmccDaOrder.setPoints(BigDecimal.valueOf(1.0));
                }
            }
        }
        // 设置分流后卡信息
        if (beforeFlowProduct != null) {
            // 如果分流则设置订单上的商品编号为分流前卡信息编号
            cmccDaOrder.setAfterFlowProductParam(cmccDaOrder.getProductParam());
            cmccDaOrder.setAfterFlowProductName(cmccDaOrder.getProductName());
            cmccDaOrder.setProductParam(beforeFlowProduct.getProductParam());
            cmccDaOrder.setProductName(beforeFlowProduct.getProductName());
        }
        //保存客户订单信息
        cmccDaOrderService.save(cmccDaOrder);
        return channelReqResult;
    }

    /**
     * @Author: GodLu
     * @Date: 2024/4/11 14:28
     * @Description: 生成订单信息
     * @param sysUser 下单用户
     * @param placeOrderDTO 下单信息
     * @param placeOrderProduct 下单卡
     * @return: CmccDaOrder
     */
    private CmccDaOrder genOrder(SysUser sysUser, PlaceOrderDTO placeOrderDTO, CmccDaProduct placeOrderProduct){
        // 转换为订单对象
        CmccDaOrder cmccDaOrder = unOrderOperationServiceConverter.placeOrderDTOToDo(placeOrderDTO, placeOrderProduct, zoningCodeMateManager, attributionCodeMateManager);
        cmccDaOrder.setCode(placeOrderDTO.getCode());//验证码
        cmccDaOrder.setPhoneUuid(placeOrderDTO.getPhoneUuid());//号码唯一id
        cmccDaOrder.setUserName(sysUser.getNickName());//用户名
        cmccDaOrder.setSubscribePath(placeOrderDTO.getSubscribePath());// 客户订购路径
        cmccDaOrder.setOpenId(placeOrderDTO.getOpenId());
        // 设置顶级代理信息
        SysUser sysUserStaffUp = sysUserMapper.selectStaffUserById(Long.valueOf(placeOrderDTO.getUserId()));
        if (sysUserStaffUp != null) {
            cmccDaOrder.setSuperiorAgentId(sysUserStaffUp.getUserId());
            cmccDaOrder.setSuperiorAgentName(sysUserStaffUp.getNickName());
        }
        // 设置下单模式完成状态为0未完成
        cmccDaOrder.setProfitConditionStatus("0");
        // 设置订单用户年龄
        int age = IdCardNumberMethod.getAgeForIdcard(cmccDaOrder.getCustomerCertNo());
        // 设置用户年龄
        cmccDaOrder.setCustomerAge(age);
        // 设置渠道ID
        cmccDaOrder.setBindChannelInfoId(Integer.valueOf(placeOrderProduct.getBindChannelInfoId()));
        // 设置渠道名称
        String sysChannel = DictUtils.getDictLabel("sys_channel", placeOrderProduct.getBindChannelInfoId());
        cmccDaOrder.setBindChannelInfoName(sysChannel);
        // 原号码
        cmccDaOrder.setSourcePhone(placeOrderDTO.getChoosePhone());
        return cmccDaOrder;
    }

    /**
     * 发送请求至三方接口
     * @param cmccDaOrder 订单信息
     * @return 接口返回msg
     */
    private ReqResult sendPlaceOrderRequestToChannel(CmccDaOrder cmccDaOrder, CmccDaProduct cmccDaProduct) {
        Channel defaultChannel = channelManager.getDefaultChannel(Integer.valueOf(cmccDaProduct.getBindChannelInfoId()));
        ReqResult reqResult = defaultChannel.placeOrder(cmccDaOrder, cmccDaProduct, addressChannelService);
        //三方返回信息
        String msg = reqResult.getMsg();
        if (reqResult.getCode() != SUCCESS_CODE){
            cmccDaOrder.setFailureReason(msg);
            cmccDaOrder.setOrderStatus(OrderStatusEnum.FAIL.getOrderStatus());
            cmccDaOrder.setOrderStatusDesc(OrderStatusEnum.FAIL.getOrderStatusDesc());
            return ReqResult.error(msg);
        }
        // data 这个TM的 data 一会时 array数组 一会是对象 草
        Object data = reqResult.getData();
        if (data instanceof JSONArray) {
            if (((JSONArray) data).isEmpty()) {
                cmccDaOrder.setOrderStatus(OrderStatusEnum.FAIL.getOrderStatus());
                cmccDaOrder.setOrderStatusDesc(OrderStatusEnum.FAIL.getOrderStatusDesc());
                cmccDaOrder.setFailureReason(msg);
                return ReqResult.error(msg);
            } else {
                placeOrderLog.error("接收的到结果为 json 数据 不符合预期 ！！值为 {}", ((JSONArray) data).toJSONString());
                log.error("接收的到结果为 json 数据 不符合预期 ！！值为 {}", ((JSONArray) data).toJSONString());
                return ReqResult.error("接收的到结果为 json 数据 不符合预期 ！！值为 {}" + ((JSONArray) data).toJSONString());
            }
        }
        if (data instanceof UnOrderResultBo) {
            UnOrderResultBo unOrderResultBo = (UnOrderResultBo) data;
            cmccDaOrder.setOrderId(unOrderResultBo.getOrderId());
            cmccDaOrder.setChannelOrderNo(unOrderResultBo.getChannelOrderNo());
            cmccDaOrder.setOrderStatus(OrderStatusEnum.UN_ORDER_SUCCESS.getOrderStatus());
            cmccDaOrder.setOrderStatusDesc(OrderStatusEnum.UN_ORDER_SUCCESS.getOrderStatusDesc());
            return ReqResult.success(msg, unOrderResultBo);
        }
        return ReqResult.error(msg);
    }

    private CmccDaProduct getAfterFlowProduct(CmccDaProduct beforeFlowProduct, ProductFlowInfo productFlowInfo){
        // 分流开关
        boolean isDistanceFlow = "1".equals(beforeFlowProduct.getDistanceFlowFlag());
        boolean isOperatorFlow = "1".equals(beforeFlowProduct.getOperatorFlowFlag());
        boolean isAreaFlow = "1".equals(beforeFlowProduct.getAreaFlowFlag());
        /** ====================================异地分流===================================== */
        //异地分流开关打开
        if (isDistanceFlow){
            //判断收货地址和归属地是否一致
            if (!StringUtils.equals(productFlowInfo.getAddressProvinceCode(), productFlowInfo.getAttributeProvinceCode())
                    || !StringUtils.equals(productFlowInfo.getAddressCityCode(), productFlowInfo.getAttributeCityCode())){//不一致的话就异地分流
                productFlowLog.info("【{}】【{}】异地分流", beforeFlowProduct.getProductName(), beforeFlowProduct.getProductCode());
                log.info("【{}】【{}】异地分流", beforeFlowProduct.getProductName(), beforeFlowProduct.getProductCode());
                //查找当前卡的所有异地分流卡
                List<CmccDaDistanceFlow> cmccDaDistanceFlowList = cmccDaDistanceFlowService.list(new LambdaQueryWrapper<CmccDaDistanceFlow>()
                        .eq(CmccDaDistanceFlow::getProductId, beforeFlowProduct.getId()));
                //如果集合不为空则继续分流
                if (!cmccDaDistanceFlowList.isEmpty()) {
                    //集合中随机获取一个异地分流信息对象
                    CmccDaDistanceFlow cmccDaDistanceFlow = cmccDaDistanceFlowList.get(new Random().nextInt(cmccDaDistanceFlowList.size()));
                    //通过异地分流信息获取分流卡
                    CmccDaProduct afterFlowProduct = cmccDaProductService.getOne(new LambdaQueryWrapper<CmccDaProduct>()
                            .eq(CmccDaProduct::getId, cmccDaDistanceFlow.getDistanceFlowProductId()));
                    productFlowLog.info("【{}】【{}】异地分流到【{}】【{}】", beforeFlowProduct.getProductName(), beforeFlowProduct.getProductCode(),
                            afterFlowProduct.getProductCode(), afterFlowProduct.getProductName());
                    log.info("【{}】【{}】异地分流到【{}】【{}】", beforeFlowProduct.getProductName(), beforeFlowProduct.getProductCode(),
                            afterFlowProduct.getProductCode(), afterFlowProduct.getProductName());
                    return afterFlowProduct;
                }
                //集合为空则继续
            }
            //一致的话继续
        }

        /** ====================================异网分流===================================== */
        // 异网分流打开
        if (isOperatorFlow){
            List<AddressSystem> addressSystemList = addressSystemService.list(new LambdaQueryWrapper<AddressSystem>()
                    .eq(AddressSystem::getProvinceCode, productFlowInfo.getAddressProvinceCode())
                    .eq(AddressSystem::getCityCode, productFlowInfo.getAddressCityCode()));
            AddressSystem addressSystem = addressSystemList.get(0);
            AddressChannel addressChannel = addressChannelService.lambdaQuery()
                    .eq(AddressChannel::getChannelId, "0")
                    .likeRight(AddressChannel::getCityName, addressSystem.getCityName().substring(0, 2))
                    .one();
            // 拼接参数
            Map<String,String> paramsMap = new HashMap<>();
            paramsMap.put("channel","01-4575-akcv-asts");
            paramsMap.put("certId", productFlowInfo.getCustomerCertNo());
            paramsMap.put("certName", productFlowInfo.getCustomerName());
            paramsMap.put("provinceCode",addressChannel.getEssProvinceCode());
            paramsMap.put("cityCode",addressChannel.getEssCityCode());
            try {
                // 如果不是异网则分流
                if (!ZopUtil.isDifferentNet(paramsMap)){
                    productFlowLog.info("【{}】【{}】异网分流", beforeFlowProduct.getProductName(), beforeFlowProduct.getProductCode());
                    log.info("【{}】【{}】异网分流", beforeFlowProduct.getProductName(), beforeFlowProduct.getProductCode());
                    //查找当前卡的所有异网分流卡
                    List<CmccDaOperatorFlow> cmccDaOperatorFlowList = cmccDaOperatorFlowService.list(new LambdaQueryWrapper<CmccDaOperatorFlow>()
                            .eq(CmccDaOperatorFlow::getProductId, beforeFlowProduct.getId()));
                    if (cmccDaOperatorFlowList != null && !cmccDaOperatorFlowList.isEmpty()){
                        //集合中随机获取一个异网分流信息对象
                        CmccDaOperatorFlow cmccDaOperatorFlow = cmccDaOperatorFlowList.get(new Random().nextInt(cmccDaOperatorFlowList.size()));
                        //通过异网分流信息获取分流卡
                        CmccDaProduct afterFlowProduct = cmccDaProductService.getOne(new LambdaQueryWrapper<CmccDaProduct>()
                                .eq(CmccDaProduct::getId, cmccDaOperatorFlow.getOperatorFlowProductId()), false);
                        productFlowLog.info("【{}】【{}】异网分流到【{}】【{}】", beforeFlowProduct.getProductName(), beforeFlowProduct.getProductCode(),
                                afterFlowProduct.getProductCode(), afterFlowProduct.getProductName());
                        log.info("【{}】【{}】异网分流到【{}】【{}】", beforeFlowProduct.getProductName(), beforeFlowProduct.getProductCode(),
                                afterFlowProduct.getProductCode(), afterFlowProduct.getProductName());
                        return afterFlowProduct;
                    }
                }
            } catch (Exception e) {
                //throw new ServiceException("异网校验服务请求失败");
                productFlowLog.error("异网校验服务请求失败");
                log.error("异网校验服务请求失败");
                return null;
            }
        }

        /** ===============================地区分流===================================== */
        //地区分流开关打开
        if (isAreaFlow){
            //查找当前卡的所有地区分流卡
            List<CmccDaAreaFlow> cmccDaAreaFlowList = cmccDaAreaFlowService.list(new LambdaQueryWrapper<CmccDaAreaFlow>()
                    .eq(CmccDaAreaFlow::getProductId, beforeFlowProduct.getId()));
            //如果集合不为空则继续分流
            if (!cmccDaAreaFlowList.isEmpty()) {
                productFlowLog.info("【{}】【{}】地区分流", beforeFlowProduct.getProductName(), beforeFlowProduct.getProductCode());
                log.info("【{}】【{}】地区分流", beforeFlowProduct.getProductName(), beforeFlowProduct.getProductCode());
                //遍历查询分流省市与当前提交信息省市相同的分流卡
                for (CmccDaAreaFlow cmccDaAreaFlow : cmccDaAreaFlowList) {
                    //System.out.println("用户地址：" + unOrderDto.getAddressProvinceCode() + " | " + unOrderDto.getAddressCityCode());
                    //System.out.println("分流地址：" + StringUtils.isEmpty(cmccDaAreaFlow.getAreaFlowProvinceCode()) + " | " + cmccDaAreaFlow.getAreaFlowCityCode());
                    //获取分流卡信息
                    CmccDaProduct afterFlowProduct = cmccDaProductService.getOne(new LambdaQueryWrapper<CmccDaProduct>()
                            .eq(CmccDaProduct::getId, cmccDaAreaFlow.getAreaFlowProductId()), false);
                    if (StringUtils.isEmpty(cmccDaAreaFlow.getAreaFlowProvinceCode())) {//省代码为空则分流到全部地区
                        productFlowLog.info("全部地区【{}】【{}】分流到【{}】【{}】", beforeFlowProduct.getProductName(), beforeFlowProduct.getProductCode(),
                                afterFlowProduct.getProductCode(), afterFlowProduct.getProductName());
                        log.info("全部地区【{}】【{}】分流到【{}】【{}】", beforeFlowProduct.getProductName(), beforeFlowProduct.getProductCode(),
                                afterFlowProduct.getProductCode(), afterFlowProduct.getProductName());
                        return afterFlowProduct;
                    } else if (StringUtils.isEmpty(cmccDaAreaFlow.getAreaFlowCityCode()) &&
                            productFlowInfo.getAddressProvinceCode().equals(cmccDaAreaFlow.getAreaFlowProvinceCode())) {//省代码不为空且市代码为空则分流到指定省
                        productFlowLog.info("{}省地区【{}】【{}】分流到【{}】【{}】", addressSystemService.getProvinceNameByCode(productFlowInfo.getAddressProvinceCode()),
                                beforeFlowProduct.getProductName(), beforeFlowProduct.getProductCode(),
                                afterFlowProduct.getProductCode(), afterFlowProduct.getProductName());
                        log.info("{}省地区【{}】【{}】分流到【{}】【{}】", addressSystemService.getProvinceNameByCode(productFlowInfo.getAddressProvinceCode()),
                                beforeFlowProduct.getProductName(), beforeFlowProduct.getProductCode(),
                                afterFlowProduct.getProductCode(), afterFlowProduct.getProductName());
                        return afterFlowProduct;
                    } else if (productFlowInfo.getAddressProvinceCode().equals(cmccDaAreaFlow.getAreaFlowProvinceCode())
                            && productFlowInfo.getAddressCityCode().equals(cmccDaAreaFlow.getAreaFlowCityCode())) {//省市代码均不为空则分流到指定省市
                        productFlowLog.info("{}省{}地区【{}】【{}】分流到【{}】【{}】", addressSystemService.getProvinceNameByCode(productFlowInfo.getAddressProvinceCode()),
                                addressSystemService.getCityNameByCode(productFlowInfo.getAddressCityCode()),
                                beforeFlowProduct.getProductName(), beforeFlowProduct.getProductCode(),
                                afterFlowProduct.getProductCode(), afterFlowProduct.getProductName());
                        log.info("{}省{}地区【{}】【{}】分流到【{}】【{}】", addressSystemService.getProvinceNameByCode(productFlowInfo.getAddressProvinceCode()),
                                addressSystemService.getCityNameByCode(productFlowInfo.getAddressCityCode()),
                                beforeFlowProduct.getProductName(), beforeFlowProduct.getProductCode(),
                                afterFlowProduct.getProductCode(), afterFlowProduct.getProductName());
                        return afterFlowProduct;
                    }
                    //其他情况一律不分流
                }
                //没有则正常下单
            }
            //集合为空则正常下单
        }
        return null;
    }

    @Override
    public JSONObject orderSearch(OrderSearchDTO orderSearchDTO) {
        QueryWrapper<CmccDaOrder> cmccDaOrderQueryWrapper = new QueryWrapper<>();
        cmccDaOrderQueryWrapper.eq("order_id", orderSearchDTO.getOrderId());
        CmccDaOrder cmccDaOrder = cmccDaOrderService.getOne(cmccDaOrderQueryWrapper);
        if (cmccDaOrder == null) {
            throw new ServiceException("订单不存在!",500);
        }
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("orderId",cmccDaOrder.getOrderId());
        jsonObject.put("preNumber",cmccDaOrder.getChoosePhone());
        jsonObject.put("orderStatus",cmccDaOrder.getOrderStatus());
        jsonObject.put("rechargeAmount",cmccDaOrder.getScMoney());
        return jsonObject;
    }
}
